import numpy as np
import pandas as pd
from sklearn.decomposition import PCA, FactorAnalysis
from sklearn import preprocessing
from factor_analyzer import FactorAnalyzer

# 取消科学计数法
np.set_printoptions(suppress=True)
df = pd.read_csv("F:/成信大/多元统计分析/test4-1.csv")
columns = df.shape[1]
data = df.columns[1: columns]
df = np.array(df[data])
# 皮尔森相关系数
df_corr = np.corrcoef(df)
# 数据标准化
df_z = preprocessing.scale(df)
# pca = PCA(n_components=2)
# 主成分得分
# newData = pca.fit_transform(df)
# print(newData)
# 累计方差
# print(pca.explained_variance_ratio_)

# print("公因子方差：\n", fa.get_communalities())
"""
因子得分就是以成分矩阵（载荷因子）作为系数构成一个线性组合（待确认）
这里不使用主成分分析的方法结果与SPSS一致
"""
# print("\n因子载荷矩阵：\n", fa.loadings_)
# variance = fa.get_factor_variance()
# print("\n特征值：\n", variance[0])
# print("\n方差贡献率：\n", variance[1])
# print("\n方差累计贡献率：\n", variance[2])

fa = FactorAnalyzer(rotation=None, n_factors=2, method='principal')
fa.fit(df_z)
print("载荷矩阵：\n", fa.loadings_)
# 使用最大方差法旋转因子载荷矩阵
# fa_is = FactorAnalysis(rotation='varimax', n_components=2)
fa_er = FactorAnalyzer(rotation='varimax', n_factors=2, method='principal')
fa_er.fit(df_z)
print("旋转后的载荷矩阵：\n", fa_er.loadings_)
print("\n因子得分（6项）：\n", fa_er.transform(df_z)[:6])
# print(pd.DataFrame(fa.components_, columns=data))
# print(fa_is.fit_transform(df_z))
# sc = fa.fit_transform(df)
# print(sc)
# 因子得分
scores = []

# def get_score(factors):
#     """
#
#     :param factors:
#     :return:
#     """
#     return sum(factors * fa_rotate.get_factor_variance()[1])


# 利用载荷因子乘以方差贡献率
# for i in range(len(fa.transform(df))):
#     score = round(get_score(fa.transform(df)[i]), 4)
#     scores.append(score)
# print(scores)

# 矩阵均值
df_mean = np.mean(df, axis=0)
# 矩阵元素减去均值
df_cut = df - df_mean
# df_cut的协方差矩阵
"""
rowvar : bool, optional
        If `rowvar` is True (default), then each row represents a
        variable, with observations in the columns. Otherwise, the relationship
        is transposed: each column represents a variable, while the rows
        contain observations.
        根据翻译：如果为True（默认），则表明传入的数据一行代表一个样本；否则，则说明传入的数据一列
        代表一个样本
        此数据需要以每行作为一个样本
"""
df_cov = np.cov(df_cut, rowvar=True)
# 特征值a,特征向量b。注意：当矩阵不是方阵时，使用其协方差阵和相关阵求解
eigValues, eigVectors = np.linalg.eig(df_cov)
# 对特征值进行升序排序，为了选择较大的特征值，这里返回的是下标
eigSortIndex = np.argsort(eigValues)
# 保留前K个最大的特征值下标，根据SPSS的结果来看，这里我们的K=2，所以取最后两个特征值
# 最后我们还需要交换这两个下标的位置，让最大的在左边，其次的在右边
eigSortIndex = eigSortIndex[-2:]
tempIndex = eigSortIndex[0]
eigSortIndex[0] = eigSortIndex[1]
eigSortIndex[1] = tempIndex
# 最大两个特征值对应的特征向量
maxVectors = eigVectors[:, eigSortIndex]
# print(maxVectors)
# print(eigVectors[:, 51])
# print(maxVectors)
pca = df.T.dot(maxVectors)
